home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / cross / Avr.lha / Atmel / Asm / src / asm.c next >
C/C++ Source or Header  |  2000-03-27  |  32KB  |  1,935 lines

  1. /************************************************************************/
  2. /* Atmel assembler V1.01                                                */
  3. /* (C)2000 LJS                                                          */
  4. /* This should compile on anything!                                     */
  5. /*                                                                      */
  6. /* 1)Removed NULL at end of constant strings                            */
  7. /* 2)Shift Left/Right (< >) is now as for C ( << >> )                   */
  8. /* 3)Removed temporary file, now done to a buffer.                      */
  9. /* 4)No upper limit on number of labels (except for avail RAM).         */
  10. /* 5)'def' added to allow small text replacements.                      */
  11. /* 6)Maths precedence is now /*+-&|<>                                   */
  12. /* 7)Source files needed a new line at the end or else the last line    */
  13. /*   would not be assembled, fixed.                                     */
  14. /************************************************************************/
  15.  
  16. #include<stdio.h>
  17. #include<string.h>
  18.  
  19. typedef unsigned long ULONG;
  20. typedef unsigned char BYTE;
  21.  
  22. #include "buff.h"
  23. #include "errors.h"
  24.  
  25. /* #define DUMP_BUFFER "tmp1.tmp" */
  26.  
  27. #define CODEFILE "Atmel.txt"
  28. #define MAXOPCODES 256
  29. #define OPLENGTH   8
  30. #define MAX_SR_LINE 16      /*16 bytes max on one S Record line*/
  31.  
  32. char *Errors[]={"OK",
  33.                                 "Bad constant",
  34.                                 "File error",
  35.                                 "Unrecognised opcode",
  36.                                 "Operand error",
  37.                                 "Out of range",
  38.                                 "Bad code generated",
  39.                                 "Use registers >15",
  40.                                 "Use registers 24, 26, 28 and 30",
  41.                                 "Redeclared label",
  42.                                 "Relative address must be even",
  43.                                 "Code must be at an even address",
  44.                                 "Can't open file for inclusion",
  45.                                 "Out of memory",
  46.                 "Missing quote's",
  47.                 "Division by zero",
  48.                 "Missing brackets",
  49.                 "Formula to complex"
  50.                              };
  51.  
  52. #define D_ORG     0
  53. #define D_END     1
  54. #define D_EQU     2
  55. #define D_INCL    3
  56. #define D_NEWFILE 4
  57. #define D_ENDNEW  5
  58. #define D_CONSTB  6
  59. #define D_CONSTW  7
  60. #define D_DEFINE  8
  61.  
  62. char *Directives[]={"ORG",
  63.                                         "END",
  64.                                         "EQU",
  65.                                         "INCLUDE",
  66.                                         "FILE",
  67.                                         "ENDFILE",
  68.                                         "DB",
  69.                                         "DW",
  70.                     "DEF",
  71.                                         NULL
  72.                                      };
  73.  
  74. struct ACode{char *Opcode;
  75.                          char *Operand;
  76.                          char *Code;
  77.                          char *Flag;
  78.                         };
  79.  
  80. struct DStack{ struct DStack *Last;
  81.                              char *Data;
  82.                              FILE *Handle;
  83.                              long Line;
  84. };
  85.  
  86. struct Labels{
  87.                struct Labels *Last;
  88.                char *Label;
  89.                int  Address;
  90.                char Flag;
  91.                char *Macro;
  92. };
  93.  
  94. struct ACode *Codes[MAXOPCODES];
  95. int Error=0;
  96. long LineNumber=0;
  97. struct DStack *Files=NULL;
  98. struct Labels *LabelStack = NULL;
  99. BYTE SRBuffer[MAX_SR_LINE];
  100. BYTE SROffset;
  101.  
  102. int SRIn=0;
  103.  
  104. #include "proto.h"
  105.  
  106. int main(int argc, char *argv[])
  107. {
  108.     FILE *Infile;
  109.   MEMBUFF *Tempfile;
  110.     int Count;
  111.     char *Outfile, *Listfile=NULL;
  112.  
  113.     printf(" Atmel cross assembler (C)2000 LJS By Lee Atkins.\n");
  114.   printf(" Version date "__DATE__"\n");
  115.     if(argc<2)
  116.     {
  117.         printf("Asm <source file> <output file> <list file>\n");
  118.         return 1;
  119.     }
  120.  
  121.     if (argc>2)
  122.     {
  123.         Outfile=argv[2];
  124.     }
  125.     else
  126.     {
  127.         Outfile="a.out";
  128.     }
  129.  
  130.     if (argc==4)
  131.     {
  132.         Listfile=argv[3];
  133.     }
  134.  
  135.     for(Count=0; Count<MAXOPCODES; Count++)
  136.     {
  137.         Codes[Count]=NULL;
  138.     }
  139.     if(ParseCodes(CODEFILE))
  140.     {
  141.         PushFiles(argv[1],NULL);
  142.     Tempfile=OpenBuffer();
  143.       if(Tempfile!=NULL)
  144.       {
  145.           if(PreProcess(argv[1],Tempfile))
  146.           {
  147.  
  148.         printf(" Assembling :%s\n Output on  :%s\n",argv[1],Outfile);
  149.               if(Listfile)
  150.               {
  151.                   printf(" List on    :%s\n",Listfile);
  152.               }
  153.               Assemble(Tempfile,Outfile,Listfile,argv[1]);
  154.           }
  155.  
  156.         if(Error)
  157.         {
  158.             printf(" File  : %s\n",Files->Data);
  159.             printf(" Error %d, Line %ld %s.\n",Error,LineNumber,Errors[Error]);
  160.         }
  161.         else
  162.         {
  163.         printf(" Bytes used : %d\n",SRIn);
  164.             printf(" Assembled with no errors.\n");
  165.         }
  166.  
  167. #ifdef DUMP_BUFFER
  168.       BuffDump(DUMP_BUFFER,Tempfile);
  169. #endif
  170.  
  171.       KillBuffer(Tempfile);
  172.     }
  173.     else
  174.     {
  175.       printf(" Out of memory!\n");
  176.     }
  177.   }
  178.     else
  179.     {
  180.       printf(" Error parsing machine file!\n");
  181.     }
  182.  
  183.   FreeCodes();
  184.     FreeLabelStack();
  185.     while(PopFiles());
  186.  
  187.     return 1;
  188. }
  189.  
  190. int ParseCodes(char *FileName)
  191. {
  192.  FILE *Infile;
  193.  int Count=0, Part=0, OneOfFour=0;
  194.  char InText, InStr[36],Finished=0;
  195.  
  196.     /*Gets code from code file FileName*/
  197.  
  198.  Infile=fopen(FileName,"r");
  199.  if(Infile==NULL)
  200.  {
  201.      return 0;
  202.  }
  203.  
  204.  do
  205.  {
  206.      do
  207.      {
  208.          do
  209.          {
  210.              InText=fgetc(Infile);
  211.          }while( (InText<33) && (InText!=EOF) );
  212.          if(InText==EOF)
  213.          {
  214.              fclose(Infile);
  215.              return 1;
  216.          }
  217.          if(InText=='*')
  218.          {
  219.        do
  220.        {
  221.          InText=fgetc(Infile);
  222.        }while( (InText!='*') && (InText!=EOF) );
  223.        if(InText==EOF)
  224.        {
  225.          fclose(Infile);
  226.          return 0;
  227.        }
  228.          }
  229.      }while(InText=='*');
  230.  
  231.      Count=0;
  232.      do
  233.      {
  234.          InStr[Count++]=InText;
  235.          if(Count==36)
  236.          {
  237.              Count--;
  238.        fclose(Infile);
  239.        return 0;
  240.          }
  241.          InText=fgetc(Infile);
  242.      if(InText=='*')
  243.      {
  244.        fclose(Infile);
  245.        return 0;
  246.      }
  247.      }while(InText>32);
  248.      InStr[Count]=0;        /*terminate*/
  249.  
  250.      switch(OneOfFour)
  251.      {
  252.          case 0:
  253.                         Codes[Part]=(struct ACode*)malloc(sizeof(struct ACode));
  254.                         if(Codes[Part]==NULL)
  255.                         {
  256.                             Finished=2;
  257.                         }
  258.             else
  259.             {
  260.               Codes[Part]->Operand=NULL;
  261.               Codes[Part]->Code=NULL;
  262.               Codes[Part]->Flag=NULL;
  263.                           Codes[Part]->Opcode=(char*)malloc(strlen(InStr)+1);
  264.                           if(Codes[Part]->Opcode==NULL)
  265.                           {
  266.                               Finished=2;
  267.                           }
  268.               else
  269.               {
  270.                             strcpy(Codes[Part]->Opcode,InStr);
  271.                             OneOfFour++;
  272.               }
  273.             }
  274.                         break;
  275.          case 1:
  276.                      Codes[Part]->Operand=(char*)malloc(strlen(InStr)+1);
  277.                      if(Codes[Part]->Operand==NULL)
  278.                      {
  279.                          Finished=2;
  280.                      }
  281.            else
  282.            {
  283.                        strcpy(Codes[Part]->Operand,InStr);
  284.                        OneOfFour++;
  285.            }
  286.                      break;
  287.          case 2:
  288.                      Codes[Part]->Code=(char*)malloc(strlen(InStr)+1);
  289.                      if(Codes[Part]->Code==NULL)
  290.                      {
  291.                          Finished=2;
  292.                      }
  293.            else
  294.            {
  295.                        strcpy(Codes[Part]->Code,InStr);
  296.                        OneOfFour++;
  297.            }
  298.                      break;
  299.          case 3:
  300.                      Codes[Part]->Flag=(char*)malloc(strlen(InStr)+1);
  301.                      if(Codes[Part]->Flag==NULL)
  302.                      {
  303.              Finished=2;
  304.                      }
  305.            else
  306.            {
  307.                        strcpy(Codes[Part]->Flag,InStr);
  308.                        OneOfFour=0;
  309.                        Part++;
  310.                        if(Part==MAXOPCODES)
  311.                        {
  312.                            Finished=2;
  313.                        }
  314.            }
  315.                      break;
  316.      } /*end switch*/
  317.  }while(!Finished);
  318.  fclose(Infile);
  319.  if(Finished==1)
  320.  {
  321.    return 1;
  322.  }
  323.  else
  324.  {
  325.    return 0;
  326.  }
  327. }
  328.  
  329. int FreeCodes()
  330. {
  331.  /*Frees Codes array*/
  332.  int Count;
  333.  for(Count=0; Count<MAXOPCODES; Count++)
  334.  {
  335.      if(Codes[Count]!=NULL)
  336.      {
  337.          if(Codes[Count]->Opcode!=NULL)
  338.          {
  339.              free(Codes[Count]->Opcode);
  340.              Codes[Count]->Opcode=NULL;
  341.          }
  342.          if(Codes[Count]->Operand!=NULL)
  343.          {
  344.              free(Codes[Count]->Operand);
  345.              Codes[Count]->Operand=NULL;
  346.          }
  347.          if(Codes[Count]->Code!=NULL)
  348.          {
  349.              free(Codes[Count]->Code);
  350.              Codes[Count]->Code=NULL;
  351.          }
  352.          if(Codes[Count]->Flag!=NULL)
  353.          {
  354.              free(Codes[Count]->Flag);
  355.              Codes[Count]->Flag=NULL;
  356.          }
  357.          free(Codes[Count]);
  358.          Codes[Count]=NULL;
  359.      }
  360.  }
  361.  return 1;
  362. }
  363.  
  364. int PreProcess(char *Filename, MEMBUFF *Tempfile)
  365. {
  366.     FILE *Infile;
  367.   char Line[128], First[128], Second[128], Third[128], *Ptr;
  368.   char TempStr[128], Flag;
  369.     int PC=0, Tmp, FileCount, WordPC=0, NewSz, Address;
  370.   struct Labels *Result;
  371.  
  372.     LineNumber=0;
  373.  
  374.     Infile=fopen(Filename,"r");
  375.     if(Infile==NULL)
  376.     {
  377.         printf("Can't open %s\n",Filename);
  378.         return 0;
  379.     }
  380.  
  381.     FileCount=0;
  382. do
  383. {
  384.     while((!feof(Infile)) && (Error==0))
  385.     {
  386.         if(fgets(Line,128,Infile)==NULL) break;
  387.         LineNumber++;
  388.         StripComments(Line);
  389.         StripCrudd(Line);
  390.         StrUpr(Line);
  391.         Ptr=StrCpyChar(First,Line,' ');
  392.         Ptr=StrCpyChar(Second,Ptr,' ');
  393.         StrCpyChar(Third,Ptr,0);
  394.         RemoveSpace(First);
  395.         RemoveSpace(Second);
  396.         RemoveChar(Second,'.');
  397.         RemoveSpace(Third);
  398.  
  399.         if(strlen(First))
  400.         { /*Add label in stack*/
  401.       if(strcmp(Second,Directives[D_EQU])==0)
  402.             {
  403.         Replace(Third);
  404.                 Address=StrToInt(Third);
  405.                 Flag='E';
  406.       }
  407.             else if(strcmp(Second,Directives[D_DEFINE])==0)
  408.       {
  409.         Replace(Third);
  410.                 Flag='M';
  411.       }
  412.       else
  413.             {
  414.                 Address=WordPC;
  415.                 Flag='A';
  416.             }
  417.       if(Error==0)
  418.       {
  419.               if(IsInStack(First))
  420.           {
  421.               Error=REPEATLABEL;
  422.                 fclose(Infile);
  423.                   return 0;
  424.               }
  425.               if(Flag=='E')
  426.         {
  427.                 Second[0]=0;
  428.                 Third[0]=0;
  429.               }
  430.         if(Flag == 'M')
  431.         {
  432.           Result = AddLabel(First, Address, Flag, Third);
  433.           Second[0]=0;
  434.                 Third[0]=0;
  435.         }
  436.         else
  437.         {
  438.           Result = AddLabel(First, Address, Flag, NULL);
  439.         }
  440.         if( Result == NULL)
  441.               {
  442.           Error=MEM;
  443.                 fclose(Infile);
  444.                   return 0;
  445.               }
  446.         First[0]=0;
  447.       }
  448.       else
  449.       {
  450.         Error=0;
  451.       }
  452.         }
  453.         if(strlen(Second))
  454.         {
  455.       ProcessOperand(Third);
  456.       Error=0;
  457.  
  458.             if( (Tmp=FindCode(Second)) !=MAXOPCODES )
  459.             {
  460.                 NewSz=CodeLength(Tmp);
  461.         PC+=NewSz;
  462.         WordPC+=NewSz>>1;
  463.             }
  464.             else
  465.             {
  466.                 /*could be a directive*/
  467.                 Tmp=FindDirective(Second);
  468.                 if(Directives[Tmp]!=NULL)
  469.                 {
  470.                     /*It is!*/
  471.                     switch(Tmp)
  472.                     {
  473.             case D_EQU:
  474.                  break;
  475.             case D_DEFINE:
  476.                  break;
  477.                         case D_CONSTB:
  478.                                  NewSz=ConstantLength(Third,1);
  479.                  PC+=NewSz;
  480.                  WordPC+=NewSz>>1;
  481.                                  break;
  482.                         case D_CONSTW:
  483.                                  NewSz=ConstantLength(Third,2);
  484.                  PC+=NewSz;
  485.                  WordPC+=NewSz>>1;
  486.                                  break;
  487.                         case D_ORG:
  488.                                  PC=StrToInt(Third);
  489.                  WordPC=PC;
  490.                                  break;
  491.                         case D_NEWFILE:
  492.                                  PushFiles(Third,NULL);
  493.                                  LineNumber=0;
  494.                                  break;
  495.                         case D_ENDNEW:
  496.                                  PopFiles();
  497.                                  break;
  498.                         case D_INCL:
  499.                                  RemoveChar(Third,'"');
  500.                                  sprintf(TempStr," FILE \"%s\" \n",Third);
  501.                  BuffPutS(TempStr,Tempfile);
  502.                                  PushFiles(Third,Infile);  /*Save current file stuff*/
  503.                                  Infile=fopen(Third,"rb");
  504.                                  if(Infile==NULL)
  505.                                  {
  506.                                      Error=NOFILE;
  507.                                      Infile=PopFiles();
  508.                                      fclose(Infile);
  509.                                      return 0;
  510.                                  }
  511.                                  First[0]=0;
  512.                                  Second[0]=0;
  513.                                  Third[0]=0;
  514.                                  FileCount++;
  515.                                  LineNumber=0;
  516.                                  break;
  517.                         case D_END:
  518.                                  First[0]=0;
  519.                                  Second[0]=0;
  520.                                  Third[0]=0;
  521.                                  break;
  522.             default:
  523.                  Error=NOTOP;
  524.                  break;
  525.                     }/*end switch*/
  526.                 }
  527.         else
  528.         {
  529.           Error=NOTOP;
  530.         }
  531.             }
  532.         }
  533.         sprintf(TempStr,"%s  %s  %s\n",First,Second,Third);
  534.     BuffPutS(TempStr,Tempfile);
  535.     }
  536.  
  537.     fclose(Infile);
  538.     if( (FileCount) && (Error==0) )
  539.     {
  540.         BuffPutS(" ENDFILE",Tempfile);
  541.         Infile=PopFiles();
  542.     }
  543. }while( (FileCount--) && (Error==0) );
  544.     if(Error==0) return 1;
  545.     return 0;
  546. }
  547.  
  548. int FreeLabelStack(void)
  549. {
  550.   struct Labels *Tmp;
  551.  
  552.   while(LabelStack)
  553.   {
  554.     Tmp = LabelStack->Last;
  555.     if(LabelStack->Macro) free(LabelStack->Macro);
  556.     if(LabelStack->Label) free(LabelStack->Label);
  557.     free(LabelStack);
  558.     LabelStack = Tmp;
  559.   }
  560.   return 1;
  561. }
  562.  
  563. struct Labels *AddLabel(char *Name, int Address, char Flag, char *Macro)
  564. {
  565.   struct Labels *Tmp;
  566.  
  567.   Tmp = (struct Labels*)malloc(sizeof(struct Labels));
  568.   if(Tmp != NULL)
  569.   {
  570.     Tmp->Last  = LabelStack;
  571.     Tmp->Macro = NULL;
  572.     Tmp->Label = (char*)malloc(strlen(Name)+1);
  573.     if(Tmp->Label != NULL)
  574.     {
  575.       strcpy(Tmp->Label, Name);
  576.       Tmp->Address = Address;
  577.       Tmp->Flag = Flag;
  578.       if(Macro)
  579.       {
  580.         Tmp->Macro = (char*)malloc(strlen(Macro)+1);
  581.         if(Tmp->Macro != NULL)
  582.         {
  583.           strcpy(Tmp->Macro, Macro);
  584.           LabelStack = Tmp;
  585.           return Tmp;
  586.         }
  587.       }
  588.       else
  589.       {
  590.         LabelStack = Tmp;
  591.         return Tmp;
  592.       }
  593.       free(Tmp->Label);
  594.     }
  595.     free(Tmp);
  596.   }
  597.   return NULL;
  598. }
  599.  
  600. int StripComments(char *Txt)
  601. {
  602.     int Len=0;
  603.  
  604.     while((*Txt!=';') && (Len<127) && (*Txt))
  605.     {
  606.         Txt++;
  607.         Len++;
  608.     if(*Txt=='"')
  609.     {
  610.       Txt++;
  611.       Len++;
  612.       while( (*Txt!='"') && (Len<127) && (*Txt) )
  613.       {
  614.         Txt++;
  615.         Len++;
  616.       }
  617.       if( (Len==127) || (*Txt!='"') )
  618.       {
  619.         Error=MISSINGQUOTE;
  620.         return 0;
  621.       }
  622.     }
  623.     }
  624.     *Txt=0;
  625.     return 1;
  626. }
  627.  
  628. int CodeLength(int Code)
  629. {
  630.     int Result;
  631.  
  632.     if(Codes[Code]==NULL)
  633.     {
  634.         return 0;
  635.     }
  636.     Result=strlen(Codes[Code]->Code);
  637.     if(strchr(Codes[Code]->Code,'!'))
  638.     {
  639.         Result-=CountChar(Codes[Code]->Code,'!');
  640.     }
  641.     Result/=OPLENGTH;
  642.  
  643.     return Result;
  644. }
  645.  
  646. int CountChar(char *S, char C)
  647. {
  648.     int Result=0;
  649.     while(*S)
  650.     {
  651.         if(*S==C)
  652.         {
  653.             Result++;
  654.         }
  655.         S++;
  656.     }
  657.     return Result;
  658. }
  659.  
  660. char *StrCpyChar(char *Dest, char *Src, char Stop)
  661. {
  662.     char C;
  663.  
  664.     if(Src==NULL)
  665.     {
  666.         *Dest=0;
  667.         return NULL;
  668.     }
  669.  
  670.     do
  671.     {
  672.         C=*Src;
  673.         Src++;
  674.         if(C==0)
  675.         {
  676.             *Dest=0;
  677.             return NULL;
  678.         }
  679.         if(C==Stop)
  680.         {
  681.             C=0;
  682.         }
  683.         *Dest=C;
  684.         Dest++;
  685.     }while(C);
  686.     while(*Src==Stop)
  687.     {
  688.         Src++;
  689.     }
  690.     return Src;
  691. }
  692.  
  693. int StripCrudd(char *S)
  694. {
  695.     while(*S)
  696.     {
  697.         if(*S<32)
  698.         {
  699.             *S=32;
  700.         }
  701.         else if(*S==':')
  702.         {
  703.             *S=' ';
  704.         }
  705.         S++;
  706.     }
  707.     return 1;
  708. }
  709.  
  710. int RemoveChar(char *S, char T)
  711. {
  712.     /*Removes a character from a string*/
  713.     char *Temp;
  714.     Temp=S;
  715.     while(*S)
  716.     {
  717.         if(*S==T)
  718.         {
  719.             *S=' ';
  720.         }
  721.         S++;
  722.     }
  723.     RemoveSpace(Temp);
  724.     return 1;
  725. }
  726.  
  727. int RemoveSpace(char *S)
  728. {
  729.     /*Removes space from a string*/
  730.     char *T;
  731.  
  732.     while(*S)
  733.     {
  734.         if(*S==' ')
  735.         {
  736.             T=S;
  737.             while(*T)
  738.             {
  739.                 *T=*(T+1);
  740.                 T++;
  741.             }
  742.         }
  743.         else
  744.         {
  745.             S++;
  746.         }
  747.     }
  748.     return 1;
  749. }
  750.  
  751. int IsInStack(char *Str)
  752. {
  753.     struct Labels *Tmp;
  754.  
  755.   Tmp = LabelStack;
  756.   while(Tmp)
  757.   {
  758.         if(strcmp(Str,Tmp->Label)==0)
  759.         {
  760.             return 1;
  761.         }
  762.     Tmp = Tmp->Last;
  763.     }
  764.     return 0;
  765. }
  766.  
  767.  
  768. int FindCode(char *Str)
  769. {
  770.     int Count;
  771.  
  772.     for (Count=0; Count<MAXOPCODES; Count++)
  773.     {
  774.         if(Codes[Count]!=NULL)
  775.         {
  776.             if(strcmp(Str,Codes[Count]->Opcode)==0)
  777.             {
  778.                 return Count;
  779.             }
  780.         }
  781.     }
  782.     return Count;
  783. }
  784.  
  785. int FindDirective(char *Str)
  786. {
  787.     int Count=0;
  788.  
  789.     while(Directives[Count])
  790.     {
  791.         if(strcmp(Str,Directives[Count])==0)
  792.         {
  793.             return Count;
  794.         }
  795.         Count++;
  796.     }
  797.     return Count;
  798. }
  799.  
  800. int ProcessOperand(char *Str)
  801. {
  802.     char *Ptr,Left[128],Right[128],Comma;
  803.  
  804.   Left[0]=0;
  805.   Right[0]=0;
  806.     Ptr=Str;
  807.     Comma=0;
  808.     while( (*Str!=',') && (*Str) )
  809.     {
  810.         Str++;
  811.     }
  812.     if(*Str==',')
  813.     {
  814.         *Str=0;
  815.         Str++;
  816.         Comma=1;
  817.     }
  818.     else
  819.     {
  820.         Str=Ptr;
  821.     }
  822.  
  823.     strcpy(Left,Ptr);
  824.     strcpy(Right,Str);
  825.     Replace(Left);
  826.     strcpy(Ptr,Left);
  827.     if(Comma)
  828.     {
  829.    Replace(Right);
  830.      strcat(Ptr,",");
  831.      strcat(Ptr,Right);
  832.     }
  833.     return 0;
  834. }
  835.  
  836. int Replace(char *Str)
  837. {
  838.   int Ret;
  839.   char Work[128],Returned[128], *Sep="+-*/&|<>)",*Tmp;
  840.   char *Orig, *Op=" ", *StrIn, BitOfMath=0;
  841.  
  842.   Work[0]=0;
  843.   Orig=Str;
  844.   StrIn=Str;
  845.   while(*Str)
  846.   {
  847.     if(*Str=='(') 
  848.     {
  849.       *Op=*Str;
  850.       strcat(Work,Op);
  851.       Orig++;
  852.     }
  853.     else
  854.     {
  855.       Tmp=Sep;
  856.       while( (*Tmp) && (*Tmp!=*Str))
  857.       {
  858.         Tmp++;
  859.       }
  860.       if(*Tmp)
  861.       {
  862.         /*Found a maths operator*/
  863.         BitOfMath=1;
  864.         *Str=0;
  865.         ReplaceLabels(Orig,Returned);
  866.         strcat(Work,Returned);
  867.         *Op=*Tmp;
  868.         strcat(Work,Op);
  869.         Orig=Str+1;
  870.       }
  871.     }
  872.     Str++;
  873.   }
  874.   ReplaceLabels(Orig,Returned);
  875.   strcat(Work,Returned);
  876.   if(BitOfMath)
  877.   {
  878.     Ret=Math(Work);
  879.     if(!Error)
  880.     {
  881.       sprintf(StrIn,"$%X",Ret);
  882.     }
  883.     else
  884.     {
  885.       strcpy(StrIn,Work);
  886.     }
  887.   }
  888.   else
  889.   {
  890.     strcpy(StrIn,Work);
  891.   }
  892.  
  893.   return 0;
  894. }
  895.  
  896. int ReplaceLabels(char *Str, char *Res)
  897. {
  898.     struct Labels *Tmp;
  899.  
  900.   strcpy(Res,Str);
  901.   Tmp = LabelStack;
  902.     while(Tmp)
  903.     {
  904.         if(Tmp->Label!=NULL)
  905.         {
  906.             if(strcmp(Str, Tmp->Label)==0)
  907.             {
  908.         if(Tmp->Macro)
  909.         {
  910.           strcpy(Res,Tmp->Macro);
  911.         }
  912.         else
  913.         {
  914.                 sprintf(Res,"$%04X",Tmp->Address);
  915.         }
  916.                 return 0;
  917.             }
  918.         }
  919.     Tmp = Tmp->Last;
  920.     }
  921.     return 0;
  922. }
  923.  
  924. int StrToInt(char *Str)
  925. {
  926.     /*Converts an asciiz number string into an int*/
  927.     /*Detects input type as being in hex,dec or bin*/
  928.     /*$aa, 0aaH is hex, %1001, 1001b is binary*/
  929.  
  930.     int Result;
  931.  
  932.     StrUpr(Str);
  933.     if(strchr(Str,'H')!=NULL)
  934.     {
  935.         Result=HexToInt(Str);
  936.     }
  937.     else if(strchr(Str,'$')!=NULL)
  938.     {
  939.         Result=HexToInt(Str);
  940.     }
  941.     else if(strchr(Str,'%')!=NULL)
  942.     {
  943.         Result=BinToInt(Str);
  944.     }
  945.     else if(strchr(Str,'B')!=NULL)
  946.     {
  947.         Result=BinToInt(Str);
  948.     }
  949.     else
  950.     {
  951.         if(!Validate(Str,"-+0123456789"))
  952.         {
  953.             Error=CONSTANT;
  954.             return 0;
  955.         }
  956.         Result=atoi(Str);
  957.     }
  958.     return Result;
  959. }
  960.  
  961. int HexToInt(char *Str)
  962. {
  963. /* converts a hex string into an int*/
  964.     int Result=0,Weight=1,C=1;
  965.     char *Tmp;
  966.  
  967.     Tmp=Str;
  968.     if(strchr(Str,'$')!=NULL)
  969.     {
  970.         Tmp=strchr(Str,'$');
  971.         Tmp++;
  972.     }
  973.     else
  974.     {
  975.         while(*Str)
  976.         {
  977.             Str++;
  978.         }
  979.         while(*Str!='H')
  980.         {
  981.             Str--;
  982.         }
  983.         *Str=0;
  984.     }
  985.     Str=Tmp+strlen(Tmp);
  986.     if(!Validate(Tmp,"0123456789ABCDEF"))
  987.     {
  988.         Error=CONSTANT;
  989.         return 0;
  990.     }
  991.     while(Str!=Tmp)
  992.     {
  993.         Str--;
  994.         Result+=(*Str<'A' ? (*Str-'0'):(10+(*Str-'A')) ) * Weight;
  995.         Weight<<=4;
  996.         C++;
  997.     }
  998.     return Result;
  999. }
  1000.  
  1001. int Validate(char *Str, char *Comp)
  1002. {
  1003.  /*Checks a string for invalid characters*/
  1004.     char *Tmp;
  1005.     BYTE Result=0;
  1006.  
  1007.     Tmp=Comp;
  1008.     while(*Str)
  1009.     {
  1010.         Comp=Tmp;
  1011.         Result=0;
  1012.         while(*Comp)
  1013.         {
  1014.             if(*Str==*Comp)
  1015.             {
  1016.                 Result=1;
  1017.             }
  1018.             Comp++;
  1019.         }
  1020.         if(Result==0)
  1021.         {
  1022.             return 0;
  1023.         }
  1024.         Str++;
  1025.     }
  1026.     return 1;
  1027. }
  1028.  
  1029. int BinToInt(char *Str)
  1030. {
  1031.  /*Converts a binary string into an int*/
  1032.     int Result=0,Weight=1;
  1033.     char *Tmp;
  1034.  
  1035.     Tmp=Str;
  1036.     if(strchr(Str,'%')!=NULL)
  1037.     {
  1038.         Tmp=strchr(Str,'%');
  1039.         Tmp++;
  1040.     }
  1041.     else
  1042.     {
  1043.         while(*Str)
  1044.         {
  1045.             Str++;
  1046.         }
  1047.         while(*Str!='B')
  1048.         {
  1049.             Str--;
  1050.         }
  1051.         *Str=0;
  1052.     }
  1053.     Str=Tmp+strlen(Tmp);
  1054.     if(!Validate(Tmp,"01"))
  1055.     {
  1056.         Error=CONSTANT;
  1057.         return 0;
  1058.     }
  1059.     while(Str!=Tmp)
  1060.     {
  1061.         Str--;
  1062.         Result+=(*Str-'0') * Weight;
  1063.         Weight<<=1;
  1064.     }
  1065.     return Result;
  1066. }
  1067.  
  1068. int Assemble(MEMBUFF *Tempfile, char *Out, char *List, char *Name)
  1069. {
  1070.     FILE *Outfile=NULL, *SRecord=NULL;
  1071.     int Count,Found,Replaced,Tmp,PC=0,OldPC=0,PrintPC=0, SRPC=0,CodePC=0;
  1072.     char Line[128], First[128], Second[128], Repeat[128], *Ptr;
  1073.     char OrigFirst[128], OrigSecond[128], Third[128];
  1074.     char Code[33], Map[8],*Indirect,*Post,*Pre, *Temp, Flag;
  1075.     ULONG CodeData, Swap;
  1076.   int Address;
  1077.  
  1078.     LineNumber=0;
  1079.  
  1080.     BuffRewind(Tempfile);
  1081.  
  1082.     if(List)
  1083.     {
  1084.         Outfile=fopen(List,"wb");
  1085.         if(Outfile==NULL)
  1086.         {
  1087.             Error=FILE_ERROR;
  1088.             return 0;
  1089.         }
  1090.     }
  1091.  
  1092.     SRecord=fopen(Out,"w");
  1093.     if(SRecord==NULL)
  1094.     {
  1095.         fclose(Outfile);
  1096.         Error=FILE_ERROR;
  1097.         return 0;
  1098.     }
  1099.  
  1100.     StartSRecord(SRecord,Name);
  1101.  
  1102.     do
  1103.     {
  1104.         do
  1105.         {
  1106.             BuffGetS(Line,128,Tempfile);
  1107.             LineNumber++;
  1108.             StripCrudd(Line);
  1109.             StrUpr(Line);
  1110.             Ptr=StrCpyChar(First,Line,' ');
  1111.             Ptr=StrCpyChar(Second,Ptr,' ');
  1112.             StrCpyChar(Third,Ptr,0);
  1113.             RemoveSpace(First);
  1114.             RemoveSpace(Second);
  1115.       RemoveSpace(Third);
  1116.         }while((strlen(Second)==0) && (!BuffEOF(Tempfile)));
  1117.  
  1118.         if(strlen(Second)==0)
  1119.         {
  1120.             FinishSRecord(SRecord,SRPC-1);
  1121.             if(Outfile)
  1122.       {
  1123.         DumpLabels(Outfile);
  1124.         fclose(Outfile);
  1125.       }
  1126.             fclose(SRecord);
  1127.             return 1;
  1128.         }
  1129.  
  1130.     strcpy(OrigFirst,Second);     /*Save for output to list file*/
  1131.         strcpy(OrigSecond,Third);
  1132.  
  1133.     if(!strchr(Third,'"'))   /*Test for a text string*/
  1134.     {
  1135.       ProcessOperand(Third);
  1136.           /*Look for code*/
  1137.  
  1138.           Indirect=strchr(Third,'X');
  1139.           if(Indirect==NULL)
  1140.           {
  1141.               Indirect=strchr(Third,'Y');
  1142.           }
  1143.           if(Indirect==NULL)
  1144.           {
  1145.               Indirect=strchr(Third,'Z');
  1146.           }
  1147.     }
  1148.     else
  1149.     {
  1150.       Indirect=NULL;
  1151.     }
  1152.  
  1153.         if(Indirect!=NULL)
  1154.         {
  1155.       Error=0;    /*These will produce an error in the maths bits*/
  1156.             Post=strchr(Third,'+');
  1157.             Pre=strchr(Third,'-');
  1158.             if(Post)
  1159.             {
  1160.                 if(Post<Indirect)
  1161.                 {
  1162.                     Pre=Post;
  1163.                     Post=NULL;
  1164.                 }
  1165.                 else if(Post>Indirect)
  1166.                 {
  1167.                     Pre=NULL;
  1168.                 }
  1169.             }
  1170.             else if(Pre)
  1171.             {
  1172.                 if(Pre>Indirect)
  1173.                 {
  1174.                     Post=Pre;
  1175.                     Pre=NULL;
  1176.                 }
  1177.                 else if(Pre<Indirect)
  1178.                 {
  1179.                     Post=NULL;
  1180.                 }
  1181.             }
  1182.         }
  1183.  
  1184.         do
  1185.         {
  1186.             Count=0;
  1187.             Found=0;
  1188.             Replaced=0;
  1189.             while((Count<MAXOPCODES) && (Codes[Count]) && (!Found))
  1190.             {
  1191.                 if(strcmp(Codes[Count]->Opcode,Second)==0)
  1192.                 {
  1193.                     if(Indirect)
  1194.                     {
  1195.                         Temp=strchr(Codes[Count]->Operand,*Indirect);
  1196.                         if(Temp!=NULL)
  1197.                         {
  1198.                             if(Pre)
  1199.                             {
  1200.                                 if(*(Temp-1)==*Pre)
  1201.                                 {
  1202.                                     Found=1;
  1203.                                 }
  1204.                             }
  1205.                             else if(Post)
  1206.                             {
  1207.                                 if(*(Temp+1)==*Post)
  1208.                                 {
  1209.                                     Found=1;
  1210.                                 }
  1211.                             }
  1212.                             else if(strchr(Third,*Temp))
  1213.                             {
  1214.                                 Found=1;
  1215.                             }
  1216.                         }
  1217.                     }
  1218.                     else
  1219.                     {
  1220.                         Found=1;
  1221.                     }
  1222.                 }
  1223.                 if(!Found)
  1224.                 {
  1225.                     Count++;
  1226.                 }
  1227.             }
  1228.             if(Found)
  1229.             {
  1230.                 if(*Codes[Count]->Flag=='A')
  1231.                 {
  1232.                     strcpy(Second,Codes[Count]->Flag+1);
  1233.                     strcpy(Repeat,Third);
  1234.                     strcat(Third,",");
  1235.                     strcat(Third,Repeat);
  1236.                     Replaced=1;
  1237.                 }
  1238.             }
  1239.         }while(Replaced);
  1240.  
  1241.         if(!Found)
  1242.         {
  1243.             if(!AsmDirective(Second))
  1244.             {
  1245.                 printf("Unrecognised Opcode.\n");
  1246.                 Error=NOTOP;
  1247.                 fclose(Outfile);
  1248.                 fclose(SRecord);
  1249.                 return 0;
  1250.             }
  1251.             else
  1252.             {
  1253.                 Tmp=FindDirective(Second);
  1254.                 if(Directives[Tmp]!=NULL)
  1255.                 {
  1256.                     /*It is!*/
  1257.                     switch(Tmp)
  1258.                     {
  1259.                         case D_CONSTB:
  1260.                                  if(Outfile)
  1261.                                  {
  1262.                                      fprintf(Outfile,"%ld\t",LineNumber);
  1263.                                      fprintf(Outfile,"%04X  ",PrintPC);
  1264.                                  }
  1265.                                  PutConstants(Outfile,SRecord,Third,&SRPC,1);
  1266.                                  if(Outfile)
  1267.                                  {
  1268.                                      fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
  1269.                                  }
  1270.                  PC=SRPC;
  1271.                                  PrintPC=SRPC>>1;
  1272.                  CodePC=PrintPC;
  1273.                                  break;
  1274.                         case D_CONSTW:
  1275.                                  if(Outfile)
  1276.                                  {
  1277.                                      fprintf(Outfile,"%ld\t",LineNumber);
  1278.                                      fprintf(Outfile,"%04X  ",PrintPC);
  1279.                                  }
  1280.                                  PutConstants(Outfile,SRecord,Third,&SRPC,2);
  1281.                                  if(Outfile)
  1282.                                  {
  1283.                                      fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
  1284.                                  }
  1285.                  PC=SRPC;
  1286.                                  PrintPC=SRPC>>1;
  1287.                  CodePC=PrintPC;
  1288.                                  break;
  1289.  
  1290.                         case D_ORG:
  1291.                                  FlushSRBuffer(SRecord,SRPC-1);
  1292.                                  PC=StrToInt(Third);
  1293.                                  PrintPC=PC;
  1294.                  CodePC=PC;
  1295.                                  SRPC=PC<<1;
  1296.                                  break;
  1297.                         case D_NEWFILE:
  1298.                                  PushFiles(Third,NULL);
  1299.                                  LineNumber=0;
  1300.                                  break;
  1301.                         case D_ENDNEW:
  1302.                                  PopFiles();
  1303.                  LineNumber++;
  1304.                                  break;
  1305.             case D_EQU:
  1306.                   Replace(Third);
  1307.                           Address=StrToInt(Third);
  1308.                           Flag='E';
  1309.                   if(IsInStack(First))
  1310.                         {
  1311.                             Error=REPEATLABEL;
  1312.                   }
  1313.                   if(AddLabel(First, Address, Flag, NULL)==NULL)
  1314.                         {
  1315.                     Error=MEM;
  1316.                   }
  1317.                   break;
  1318.                     }
  1319.                 }
  1320.             }
  1321.         }
  1322.         else
  1323.         {
  1324.             strcpy(Code,Codes[Count]->Code);
  1325.             strcpy(Map,Codes[Count]->Operand);
  1326.             OldPC=PC;
  1327.             PC+=CodeLength(Count);  /*Next address*/
  1328.       CodePC+=(PC-OldPC)>>1;
  1329.             CodeData=CreateCode(Code,Map,Third,Codes[Count]->Flag,CodePC);
  1330.             if(Outfile)
  1331.             {
  1332.                 fprintf(Outfile,"%ld\t",LineNumber);
  1333.                 fprintf(Outfile,"%04X  %04lX ",PrintPC,CodeData);
  1334.         PrintPC+=(PC-OldPC)>>1;
  1335.                 fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
  1336.             }
  1337.             if( (PC-OldPC)==4)
  1338.             {
  1339.                 PutSRBuffer(SRecord,CodeData>>16,SRPC);
  1340.                 PutSRBuffer(SRecord,(CodeData>>24)&255,SRPC+1);
  1341.         PutSRBuffer(SRecord,CodeData&255,SRPC+2);
  1342.               PutSRBuffer(SRecord,CodeData>>8,SRPC+3);
  1343.             }
  1344.       else
  1345.       {
  1346.         PutSRBuffer(SRecord,CodeData&255,SRPC);
  1347.               PutSRBuffer(SRecord,CodeData>>8,SRPC+1);
  1348.       }
  1349.       if(SRPC&1)
  1350.             {
  1351.                 printf("Asm error.\n");
  1352.                 Error=ALLIGNMENT;
  1353.             }
  1354.             SRPC+=(PC-OldPC);
  1355.         }
  1356.  
  1357.     }while( (!BuffEOF(Tempfile)) && (Error==0) );
  1358.     FinishSRecord(SRecord,SRPC);
  1359.     if(Outfile)
  1360.     {
  1361.         DumpLabels(Outfile);
  1362.         fclose(Outfile);
  1363.     }
  1364.     fclose(SRecord);
  1365.     return 1;
  1366. }
  1367.  
  1368. ULONG CreateCode(char *Code, char *Map, char *Operand, char *Flag,int PC)
  1369. {
  1370.     char Part[128], *Temp, MapPart[128], *MapTemp;
  1371.     int Count, Work, Steps, Step,Len;
  1372.     ULONG Result;
  1373.  
  1374.     if(strcmp(Map,"-")==0)
  1375.     {
  1376.         Result=BinToULong(Code);
  1377.         return Result;
  1378.     }
  1379.  
  1380.     memset(MapPart,0,128);
  1381.  
  1382.     Temp=Code;
  1383.     if(strchr(Map,',')!=NULL)
  1384.     {
  1385.         Steps=2;
  1386.     }
  1387.     else
  1388.     {
  1389.         Steps=1;
  1390.     }
  1391.  
  1392.     for(Step=0; Step<Steps; Step++)
  1393.     {
  1394.         Code=Temp;
  1395.         if (Validate(Code,"01"))
  1396.         {
  1397.             break;
  1398.         }
  1399.  
  1400.         Len=strlen(Code);
  1401.         Count=0;
  1402.         MapTemp=Map;
  1403.         while((*Operand) && (*Operand!=','))
  1404.         {
  1405.             Part[Count]=*Operand;
  1406.             MapPart[Count]=*Map;
  1407.             Count++;
  1408.             Operand++;
  1409.             Map++;
  1410.         }
  1411.         Part[Count]=0;
  1412.         MapPart[Count]=0;
  1413.         Map=MapTemp;
  1414.  
  1415.         if(*Map=='R')
  1416.         {
  1417.             if(Part[0]=='R')
  1418.             {
  1419.                 Work=StrToInt(&Part[1]);
  1420.                 if(*Flag=='S')
  1421.                 {
  1422.                     if(Work<16)
  1423.                     {
  1424.                         Error=REG16;
  1425.                         return 0;
  1426.                     }
  1427.                     Work-=16;
  1428.                 }
  1429.                 if(*Flag=='U')
  1430.                 {
  1431.                     if( (Work<24) || (Work&1) )
  1432.                     {
  1433.                         Error=UPPERREGS;
  1434.                         return 0;
  1435.                     }
  1436.                     Work=(Work>>1)&3;
  1437.                 }
  1438.                 Map++;
  1439.             }
  1440.             else
  1441.             {
  1442.                 Error=WRONGOP;
  1443.                 return 0;
  1444.             }
  1445.         }
  1446.         else if(*Map=='k')
  1447.         {
  1448.             if( (strchr(Operand,',')!=NULL) && (Steps==1) )
  1449.             {
  1450.                 Error=WRONGOP;
  1451.                 return 0;
  1452.             }
  1453.             Work=StrToInt(Part);
  1454.             if(*Flag=='R')
  1455.             {
  1456.                 Work=(Work-PC);
  1457.  
  1458.                 if((Work>63) || (Work<-64))
  1459.                 {
  1460.                     Error=RANGE;
  1461.                     return 0;
  1462.                 }
  1463.                 Work&=127;
  1464.             }
  1465.             else if(*Flag=='L')
  1466.             {
  1467.                 Work=(Work-PC);
  1468.                 Work&=4095;
  1469.             }
  1470.       else if(*Flag=='N')
  1471.             {
  1472.                 Work&=0xFFFF;
  1473.             }
  1474.         }
  1475.         else if(*Map=='K')
  1476.         {
  1477.             Work=StrToInt(Part);
  1478.         }
  1479.         else if(MapPart[2]=='q')
  1480.         {
  1481.             Work=StrToInt(&Part[2]);
  1482.             Map+=2;
  1483.         }
  1484.         else
  1485.         {
  1486.          if(!Validate(MapPart,"XYZ,+-"))
  1487.          {
  1488.              Work=StrToInt(Part);
  1489.          }
  1490.          else
  1491.          {
  1492.              Work=0;
  1493.          }
  1494.         }
  1495.  
  1496.         Code+=(Len-1);
  1497.         while(Len)
  1498.         {
  1499.             if( (*Code=='!') && (*(Code+1)!='K') )
  1500.             {
  1501.                 Code++;
  1502.                 if(*Code=='1')
  1503.                 {
  1504.                     *Code='0';
  1505.                 }
  1506.                 else
  1507.                 {
  1508.                     *Code='1';
  1509.                 }
  1510.                 Code--;
  1511.                 *Code=' ';
  1512.                 RemoveSpace(Code);
  1513.             }
  1514.             if(*Code==*Map)
  1515.             {
  1516.                 if(Work&1)
  1517.                 {
  1518.                     *Code='1';
  1519.                 }
  1520.                 else
  1521.                 {
  1522.                     *Code='0';
  1523.                 }
  1524.                 Work>>=1;
  1525.             }
  1526.  
  1527.             if(*Code=='X')     /*Don't care bit*/
  1528.             {
  1529.                 *Code='0';
  1530.             }
  1531.  
  1532.             Code--;
  1533.             Len--;
  1534.         }
  1535.         if(Work>0)          /*-ve numbers are ok!*/
  1536.         {
  1537.             Error=RANGE;
  1538.             return 0;
  1539.         }
  1540.         Operand++;
  1541.         while( (*Map) && (*Map!=',') )
  1542.         {
  1543.             Map++;
  1544.         }
  1545.         Map++;
  1546.     }
  1547.     Code=Temp;
  1548.     Result=BinToULong(Code);
  1549.     return Result;
  1550. }
  1551.  
  1552. ULONG BinToULong(char *Str)
  1553. {
  1554. /*Converts binary to ulong!*/
  1555.     int Len;
  1556.     ULONG Weight=1,Result=0;
  1557.  
  1558.     StripDontCare(Str);
  1559.     Len=strlen(Str);
  1560.     Str+=Len-1;
  1561.     while(Len)
  1562.     {
  1563.         if(Weight==0)
  1564.         {
  1565.             Error=RANGE;
  1566.             return 0;
  1567.         }
  1568.         if(*Str=='1')
  1569.         {
  1570.             Result|=Weight;
  1571.         }
  1572.         else if(*Str!='0')
  1573.         {
  1574.             Error=BADCODE;
  1575.             return 0;
  1576.         }
  1577.         Weight<<=1;
  1578.         Str--;
  1579.         Len--;
  1580.     }
  1581.     return Result;
  1582. }
  1583.  
  1584. int StripDontCare(char *Str)
  1585. {
  1586. /*Replaces 'X' with '0' in a string*/
  1587.     while(*Str)
  1588.     {
  1589.         if(*Str=='X')
  1590.         {
  1591.             *Str='0';
  1592.         }
  1593.         Str++;
  1594.     }
  1595.     return 1;
  1596. }
  1597.  
  1598. int AsmDirective(char *Str)
  1599. {
  1600.     int Count=0;
  1601.  
  1602.     while(Directives[Count]!=NULL)
  1603.     {
  1604.         if(strcmp(Str,Directives[Count])==0)
  1605.         {
  1606.             return 1;
  1607.         }
  1608.         Count++;
  1609.     }
  1610.     return 0;
  1611. }
  1612.  
  1613. int PushFiles(char *Str, FILE *H)
  1614. {
  1615.     struct DStack *Temp;
  1616.  
  1617.     if(Files==NULL)
  1618.     {
  1619.         Files=(struct DStack*)malloc(sizeof(struct DStack));
  1620.         if(Files==NULL)
  1621.         {
  1622.             Error=MEM;
  1623.             return 0;
  1624.         }
  1625.         Files->Last=NULL;
  1626.         Files->Data=(char*)malloc(strlen(Str)+1);
  1627.         if(Files->Data==NULL)
  1628.         {
  1629.             Error=MEM;
  1630.             return 0;
  1631.         }
  1632.         Files->Line=LineNumber;
  1633.         Files->Handle=H;
  1634.         strcpy(Files->Data,Str);
  1635.     }
  1636.     else
  1637.     {
  1638.         Temp=Files;
  1639.         Files=(struct DStack*)malloc(sizeof(struct DStack));
  1640.         if(Files==NULL)
  1641.         {
  1642.             Error=MEM;
  1643.             Files=Temp;
  1644.             return 0;
  1645.         }
  1646.         Files->Last=Temp;
  1647.         Files->Data=(char*)malloc(strlen(Str)+1);
  1648.         if(Files->Data==NULL)
  1649.         {
  1650.             Error=MEM;
  1651.             return 0;
  1652.         }
  1653.         strcpy(Files->Data,Str);
  1654.         Files->Line=LineNumber;
  1655.         Files->Handle=H;
  1656.     }
  1657.     return 1;
  1658. }
  1659.  
  1660. FILE *PopFiles(void)
  1661. {
  1662.     struct DStack *Temp;
  1663.     FILE *TempFile;
  1664.  
  1665.     if(Files)
  1666.     {
  1667.         if(Files->Data!=NULL)
  1668.         {
  1669.             free(Files->Data);
  1670.             Files->Data=NULL;
  1671.         }
  1672.         LineNumber=Files->Line;
  1673.         TempFile=Files->Handle;
  1674.         Temp=Files->Last;
  1675.         free(Files);
  1676.         Files=Temp;
  1677.         return TempFile;
  1678.     }
  1679.     return NULL;
  1680. }
  1681.  
  1682. int StartSRecord(FILE *File, char *Name)
  1683. {
  1684.     int Checksum, Temp;
  1685.     char *Orig;
  1686.  
  1687.     Orig=Name;
  1688.     fprintf(File,"S0");
  1689.     Temp=0;
  1690.     while( (*Name) && (*Name!='.') )
  1691.     {
  1692.         Temp++;
  1693.         Name++;
  1694.     }
  1695.     Name=Orig;
  1696.     Temp+=3;      /*+address +checksum*/
  1697.     Checksum=Temp;
  1698.     fprintf(File,"%02X",Temp);
  1699.     fprintf(File,"0000");
  1700.     while( (*Name) && (*Name!='.') )
  1701.     {
  1702.         fprintf(File,"%02X",*Name);
  1703.         Checksum+=*Name;
  1704.         Name++;
  1705.     }
  1706.     Checksum=~Checksum;
  1707.     fprintf(File,"%02X\n",(Checksum&255));
  1708.     SROffset=0;
  1709.     return 1;
  1710. }
  1711.  
  1712. int PutSRBuffer(FILE *File, BYTE Data, int PC)
  1713. {
  1714.   SRIn++;
  1715.  
  1716.     SRBuffer[SROffset]=Data;
  1717.     SROffset++;
  1718.     if(SROffset==MAX_SR_LINE)
  1719.     {
  1720.         FlushSRBuffer(File,PC);
  1721.     }
  1722.     return 1;
  1723. }
  1724.  
  1725. int FlushSRBuffer(FILE *Outfile,int PC)
  1726. {
  1727.     int C,Count;
  1728.     int Checksum;
  1729.  
  1730.     Count=SROffset;
  1731.     if(Count==0)
  1732.     {
  1733.         return 1;
  1734.     }
  1735.     fprintf(Outfile,"S1");
  1736.     fprintf(Outfile,"%02X",Count+3);  /*+3 for checksum and address*/
  1737.     Checksum=Count+3;
  1738.     fprintf(Outfile,"%04X",PC-Count+1);
  1739.     Checksum+=((PC-Count+1)>>8);
  1740.     Checksum+=((PC-Count+1)&255);
  1741.     for(C=0; C<Count; C++)
  1742.     {
  1743.         fprintf(Outfile,"%02X",SRBuffer[C]);
  1744.         Checksum+=SRBuffer[C];
  1745.     }
  1746.     Checksum=~Checksum;
  1747.     fprintf(Outfile,"%02X\n",(Checksum&255));
  1748.     SROffset=0;
  1749.     return 1;
  1750. }
  1751.  
  1752. int FinishSRecord(FILE *F,int PC)
  1753. {
  1754.      FlushSRBuffer(F,PC);
  1755.      fprintf(F,"S9030000FC\n");
  1756.      return 1;
  1757. }
  1758.  
  1759. int ConstantLength(char *S, BYTE Size)
  1760. {
  1761.     char Work[128];
  1762.     int Os,Result=0;
  1763.  
  1764.     do
  1765.     {
  1766.     Os=0;
  1767.         while((*S) && (*S!=','))
  1768.         {
  1769.             Work[Os]=*S;
  1770.             Os++;
  1771.             if(Os==128)
  1772.             {
  1773.                 Os--;
  1774.             }
  1775.             S++;
  1776.         }
  1777.         Work[Os]=0;
  1778.         if(*S==',')
  1779.         {
  1780.             S++;
  1781.         }
  1782.         Os=0;
  1783.         if(Work[Os]=='"')
  1784.         {
  1785.             Os++;
  1786.             while((Work[Os]!='"') && (Work[Os]))
  1787.             {
  1788.                 Result+=Size;  /*Do we want word long chars? !!!!*/
  1789.                 Os++;
  1790.             }
  1791.             /* Result+=Size; */   /*For the NULL, Dont put a null*/
  1792.         }
  1793.         else
  1794.         {
  1795.             Result+=Size;
  1796.         }
  1797.     }while(*S);
  1798.  
  1799.     return Result;
  1800. }
  1801.  
  1802. int PutConstants(FILE *List,FILE *Out,char *S,int *PC, BYTE Size)
  1803. {
  1804.     char Work[128];
  1805.     unsigned int Temp;
  1806.     int Os, Width=0;
  1807.  
  1808.     do
  1809.     {
  1810.         Os=0;
  1811.         while((*S) && (*S!=','))
  1812.         {
  1813.             Work[Os]=*S;
  1814.             Os++;
  1815.             if(Os==128)
  1816.             {
  1817.                 Os--;
  1818.             }
  1819.             S++;
  1820.         }
  1821.         Work[Os]=0;
  1822.         if(*S==',')
  1823.         {
  1824.             S++;
  1825.         }
  1826.         Os=0;
  1827.         if( (Work[Os]=='"') && (Size==1) )
  1828.         {
  1829.             Os++;
  1830.             while((Work[Os]!='"') && (Work[Os]))
  1831.             {
  1832.                 PutSRBuffer(Out,(BYTE)Work[Os],*PC);
  1833.                 if(List)
  1834.                 {
  1835.                     fprintf(List,"%02X",Work[Os]);
  1836.           Width++;
  1837.           if(Width==2)
  1838.           {
  1839.             Width=0;
  1840.             fprintf(List,"\n              ");
  1841.           }
  1842.                 }
  1843.                 *PC=*PC+1;
  1844.                 Os++;
  1845.             }
  1846.       /*  Dont stuff in a null !!!
  1847.             **PutSRBuffer(Out,0,*PC);
  1848.             ***PC=*PC+1;
  1849.       **if(List)
  1850.             **{
  1851.             **    fprintf(List,"00");
  1852.             **}
  1853.       */
  1854.         }
  1855.         else
  1856.         {
  1857.             Temp=StrToInt(Work);
  1858.             if(List)
  1859.             {
  1860.                 fprintf(List,"%02X",Temp&255);
  1861.         Width++;
  1862.         if(Width==2)
  1863.         {
  1864.           Width=0;
  1865.           fprintf(List,"\n              ");
  1866.         }
  1867.             }
  1868.             PutSRBuffer(Out,Temp&255,*PC);
  1869.             *PC=*PC+1;
  1870.             if(Size==2)
  1871.             {
  1872.                 if(List)
  1873.                 {
  1874.                     fprintf(List,"%02X",Temp>>8);
  1875.           Width++;
  1876.           if(Width==2)
  1877.           {
  1878.             Width=0;
  1879.             fprintf(List,"\n              ");
  1880.           }
  1881.                 }
  1882.                 PutSRBuffer(Out,Temp>>8,*PC);
  1883.                 *PC=*PC+1;
  1884.             }
  1885.         }
  1886.     }while(*S);
  1887.     return 1;
  1888. }
  1889.  
  1890. void StrUpr(char *String)
  1891. {
  1892.   BYTE TextCount=0;
  1893.  
  1894.   while(*String)
  1895.   {
  1896.     if(*String=='"') /*Dont upper constant text*/
  1897.     {
  1898.       TextCount=~TextCount;
  1899.     }
  1900.     if ( ('a' <= *String) && (*String <= 'z') && (TextCount==0) )
  1901.     {
  1902.           *String= *String + 'A' - 'a';
  1903.     }
  1904.     String++;
  1905.   }
  1906. }
  1907.  
  1908. void DumpLabels(FILE *List)
  1909. {
  1910.     struct Labels *Tmp;
  1911.   fprintf(List,"\n\n");
  1912.  
  1913.   Tmp = LabelStack;
  1914.     while(Tmp)
  1915.     {
  1916.         if(Tmp->Label!=NULL)
  1917.         {
  1918.       if(Tmp->Flag=='E')
  1919.       {
  1920.               fprintf(List,"%s\t\t$%04X\tE\n",Tmp->Label,Tmp->Address);
  1921.       }
  1922.       else if(Tmp->Flag == 'M')
  1923.       {
  1924.         fprintf(List,"%s\t\t%s\tM\n",Tmp->Label,Tmp->Macro);
  1925.       }
  1926.       else
  1927.       {
  1928.         fprintf(List,"%s\t\t$%04X\tL\n",Tmp->Label,Tmp->Address);
  1929.       }
  1930.         }
  1931.     Tmp = Tmp->Last;
  1932.     }
  1933. }
  1934.  
  1935.